#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <Math/LB_Math.h>

#ifndef LB_POLYNOMIAL_H_
#define LB_POLYNOMIAL_H_

#define Polynomial LB_Polynomial
#ifdef __cplusplus
extern "C" {
#endif
    
typedef struct LB_Polynomial{
    int degree; // 多项式的最高次数
    double *coefficients; // 多项式的系数数组
} LB_Polynomial;

static inline void lb_polynomial_init(Polynomial*p)
{
    p->degree=-1;
    p->coefficients=NULL;
}

static inline void lb_polynomial_initn(Polynomial*p,int degree)
{
    p->degree=degree;
    p->coefficients = (double *)malloc((degree + 1) * sizeof(double));
    memset(p->coefficients,0,sizeof(double)*(degree+1));
}
void resetpolynomial(int degree,Polynomial* result);

void printpolynomial(Polynomial p);
//result 可以等于p1或者p2
void addpolynomials(Polynomial* p1, Polynomial* p2,Polynomial* result);
// result不可以等于p1或者p2
void multiplypolynomials(Polynomial* p1, Polynomial* p2,Polynomial*result);

//result不可以等于p
void polynomialshift_root(Polynomial* p,double offset,Polynomial* result);


static inline void polynomialmultdouble(Polynomial* p,double fac,Polynomial* result)
{
   
    if(p==NULL){return ;}
    for (int i = 0; i <= p->degree; i++)
    {
        result->coefficients[i]=p->coefficients[i]*fac;
    }

}
// void polynomialmultdouble(Polynomial* p1,double fac,Polynomial* result);

double get_polynomial_fun_value(Polynomial* p1,double x);

int getsolutions(Polynomial *p,const double c,double r[][2]);

void simplifypolynomial(Polynomial* result);

void differentiatepolynomial(Polynomial* p,Polynomial*result);

void  integratepolynomial(Polynomial* p,Polynomial*result);




static inline void lb_polynomial_free(Polynomial*p)
{
    if(p==NULL){return;}
    SAFE_FREE(p->coefficients);
    free(p);
}

// piecewise polynomial
// 
typedef struct Basic_Piecewise_Polynomial{
    Polynomial* p1;
    double breakpoint;
    Polynomial* p2;

} Basic_Piecewise_Polynomial;

static inline void basic_piecewise_polynomial_init(
    Basic_Piecewise_Polynomial*bpp)
{
    bpp->breakpoint=0;
    bpp->p1=NULL;    bpp->p2=NULL;

}

static inline void basic_piecewise_polynomial_initn(
    Basic_Piecewise_Polynomial*bpp,int degree)
{
    bpp->breakpoint=0;
    bpp->p1=(Polynomial*)malloc(sizeof(Polynomial));
    lb_polynomial_initn(bpp->p1,degree);
    bpp->p2=(Polynomial*)malloc(sizeof(Polynomial));
    lb_polynomial_initn(bpp->p2,degree);
}

typedef struct Piecewise_Polynomial{
    int count;
    Basic_Piecewise_Polynomial**bpps;
} Piecewise_Polynomial;


static inline void piecewise_polynomial_init(Piecewise_Polynomial *p) {
    p->count = 0;
    p->bpps = NULL;
}

static inline void piecewise_polynomial_initn(
    Piecewise_Polynomial *p,int count) {
    p->count = count;
    p->bpps =(Basic_Piecewise_Polynomial**)malloc(sizeof(Basic_Piecewise_Polynomial*)*count);
    memset(p->bpps,0,sizeof(Basic_Piecewise_Polynomial*)*count);
}


#ifdef __cplusplus
}
#endif
#endif
#undef Polynomial
